package com.ls.userlog.aspect;

import com.ls.userlog.annocation.RiseLog;
import com.ls.userlog.entity.LogPojo;
import com.ls.userlog.service.LogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 定义一个切面
 */
@Aspect
@Component
@Slf4j
public class ServiceLogAspect {

    @Autowired
    private LogService logService;

    //切点
    @Pointcut("execution(* com.ls.userlog.controller..*.*(..))")
    public void savelog(){};

    /**
     * 这里定义了一个获取注解的方法，就是为了获取Controller层的具体操作。
     * 是否存在注解， 如果存在就获取
     * @param joinPoint
     */
    private static RiseLog getAnnotationLog(JoinPoint joinPoint){

        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if(method != null){
            //获得注解 @RiseLog
            return method.getAnnotation(RiseLog.class);
        }
        return null;
    }

    //方法的返回值注入给ret   @AfterReturning在切入点return内容之后切入内容：例如，一个方法没有抛出任何异常，正常返回
    @AfterReturning(returning = "ret", pointcut = "savelog()")
    public void doafter(JoinPoint joinPoint, Object ret){
            //获得注解
            RiseLog controllerLog = getAnnotationLog(joinPoint);
            //获取servlet请求对象
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            //获取用户ip
            String ip = request.getRemoteAddr();
            //向controller中发起的请求地址
            String url = request.getRequestURI();
            //方法
            String method = joinPoint.getSignature().getName();
            String param = Arrays.toString(joinPoint.getArgs());
            log.info("用户ip: " + ip);
            log.info("url: " + url);
            log.info("方法: " + method);
            log.info("参数: " + param);
            if (controllerLog != null) {
                //获取注解中的参数值
                String operateName = controllerLog.operateName();
                log.info("用户操作名称: " + operateName);
                LogPojo logPojo = new LogPojo();
                logPojo.setIp(ip);
                logPojo.setMethod(method);
                logPojo.setOperateName(operateName);
                logPojo.setUrl(url);
                logPojo.setParam(param);
                logPojo.setResult("执行成功");
                //添加日志操作
                logService.create(logPojo);
            }
    }



    //方法抛出异常时执行
    @AfterThrowing(pointcut = "savelog()", throwing = "ex")
    public void after(JoinPoint joinPoint, Exception ex){
        //获得注解
        RiseLog controllerLog = getAnnotationLog(joinPoint);
        //获取servlet请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //获取用户ip
        String ip = request.getRemoteAddr();
        //向controller中发起的请求地址
        String url = request.getRequestURI();
        //方法
        String method = joinPoint.getSignature().getName();
        String param = Arrays.toString(joinPoint.getArgs());
        log.info("用户ip: " + ip);
        log.info("url: " + url);
        log.info("方法: " + method);
        log.info("参数: " + param);
        if (controllerLog != null) {
            //获取注解中的参数值
            String operateName = controllerLog.operateName();
            log.info("用户操作名称: " + operateName);
            LogPojo logPojo = new LogPojo();
            logPojo.setIp(ip);
            logPojo.setMethod(method);
            logPojo.setOperateName(operateName);
            logPojo.setUrl(url);
            logPojo.setParam(param);
            logPojo.setResult("执行失败");
            //添加日志操作
            logService.create(logPojo);
        }
    }
}


















